#!/usr/bin/env python
# coding=utf-8
# @FileName :ini_util.py
# @Time     :2022/2/10 10:57
# @Author   :ZXC
# @Desc     :INI文件工具类
import json
from configparser import ConfigParser, MissingSectionHeaderError, NoSectionError, NoOptionError, DuplicateOptionError
from pathlib import Path
from string import Template

from loguru import logger


class INIUtil(object):
    def __init__(self, file_path=None):
        """
        INI工具类初始化方法
        Args:
            file_path: INI文件路径
        """
        # default_ini = CONFIG_DIR.joinpath('config.ini')

        if not file_path or not Path(file_path).exists() or Path(file_path).suffix != '.ini':
            raise FileNotFoundError(f'INI文件【{file_path}】未找到，初始化INI工具类失败')

        logger.debug(f'正在读取INI文件【{file_path}】')
        try:
            self.config_parser = ConfigParser(allow_no_value=True)
            self.config_parser.read(filenames=file_path, encoding='utf-8')
            logger.debug(f'初始化INI工具类完成，使用INI文件【{file_path}】')
        except FileNotFoundError:
            raise FileNotFoundError(f'INI文件【{file_path}】未找到，初始化INI工具类失败')
        except MissingSectionHeaderError:
            raise ValueError(f'INI文件【{file_path}】内容section格式不正确，初始化INI工具类失败')
        except DuplicateOptionError:
            raise ValueError(f'INI文件【{file_path}】内容存在重复的option值，初始化INI工具类失败')
        except Exception as e:
            raise ValueError(f'初始化INI文件【{file_path}】失败{e}')

    def get_option(self, section, option):
        """
        获取指定节点的指定子项
        Args:
            section:
            option:

        Returns:

        """
        logger.debug(f'正在获取{section}节点下的{option}子项')
        try:
            value = self.config_parser.get(section=section, option=option)
            logger.debug(f'获取子项成功，返回值：{value}')
            return value
        except NoSectionError:
            raise NoSectionError(f'未找到[{section}]节点')
        except NoOptionError:
            raise NoSectionError(f'未找到[{section}]节点下的{option}子项')
        except Exception as e:
            raise Exception(f'正在获取{section}节点下的{option}子项失败{e}')

    def get_default(self, option):
        """
        获取DEFAULT的指定子项
        Args:
            option:

        Returns:

        """
        logger.debug(f'正在获取[DEFAULT]节点下的{option}子项')
        try:
            value = self.config_parser.get(section='DEFAULT', option=option)
            logger.debug(f'获取子项成功，返回值：{value}')
            return value
        except NoSectionError:
            raise NoSectionError(f'未找到[DEFAULT]节点')
        except NoOptionError:
            raise NoSectionError(f'未找到[DEFAULT]节点下的{option}子项')
        except Exception as e:
            raise Exception(f'正在获取[DEFAULT]节点下的{option}子项失败{e}')

    def read_and_replace(self, section, option, data_pool: dict):
        """
        读取INI数据，并替换与数据池匹配的数据
        匹配格式为${var_name}
        Args:
            data_pool: 数据池，字典格式
            section: 节点
            option: 选项
        Returns:


        """
        ini_data = self.get_option(section, option)
        logger.debug(f'正在解析替换数据{ini_data},数据池为：{data_pool}')
        try:
            ini_data_str = json.dumps(ini_data)
            value = Template(ini_data_str).safe_substitute(data_pool)
            logger.debug(f'解析替换数据完成')
            return value
        except Exception as e:
            raise Exception(f'替换与数据池匹配的数据时出错{e}')


if __name__ == '__main__':
    from config.settings import CONFIG_DIR

    filepath = CONFIG_DIR.joinpath('config.ini')
    print(INIUtil(file_path=filepath).get_default('asd'))
